package com.mingqijia.gassafety.webserver.service.strategy;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gap.cache.redis.RedisCache;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.util.StringUtil;
import com.mingqijia.gassafety.db.entity.*;
import com.mingqijia.gassafety.db.mapper.*;
import com.mingqijia.gassafety.shared.constant.*;
import com.mingqijia.gassafety.shared.dto.AssembleTemplateDTO;
import com.mingqijia.gassafety.shared.dto.TaskDetailParamDTO;
import com.mingqijia.gassafety.shared.dto.TaskDetailRespDTO;
import com.mingqijia.gassafety.shared.utils.RedisCacheExt;
import com.mingqijia.gassafety.shared.utils.commonUtils.SnowflakeUtil;
import com.mingqijia.gassafety.shared.utils.message.SendMessageService;
import com.mingqijia.gassafety.shared.vcc.VccAuthoritiesProvider;
import com.mingqijia.gassafety.webserver.service.BusinessNoticeService;
import com.mingqijia.gassafety.webserver.service.ConsumerService;
import com.mingqijia.gassafety.webserver.service.ServicePkgRecordService;
import com.mingqijia.gassafety.webserver.service.impl.CompanyServiceImpl;
import com.mingqijia.gassafety.webserver.service.impl.EquipmentServiceImpl;
import com.mingqijia.gassafety.webserver.service.impl.WarningRecordServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static com.mingqijia.gassafety.webserver.service.impl.WarnStrategyServiceImpl.getKeys;


/**
 * @author zhangfei
 * @version 1.0.0
 * @ClassName StrategyServiceImpl.java
 * @Description
 * @createTime 2022年02月28日
 */

@Component
@Slf4j
public class StrategyServiceImpl {

    @Autowired
    RedisCache redisCache;
    @Autowired
    ConsumerMapper consumerMapper;
    @Autowired
    CustomerSubsMapper customerSubsMapper;
    @Autowired
    DtuMapper dtuMapper;
    @Autowired
    WarnStrategyExtMapper warnStrategyExtMapper;
    @Autowired
    ContactsMapper contactsMapper;
    @Autowired
    SendMessageService sendMessageService;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    DictionaryMapper dictionaryMapper;
    @Autowired
    WarnStrategyMapper warnStrategyMapper;
    @Autowired
    WarningRecordMapper warningRecordMapper;
    @Autowired
    WarningRecordServiceImpl warningRecordService;
    @Autowired
    EquipmentServiceImpl equipmentService;
    @Autowired
    CompanyServiceImpl companyService;


    @Autowired
    BusinessNoticeMapper noticeMapper;

    @Autowired
    BusinessNoticeService businessNoticeService;

    @Autowired
    ServicePkgRecordService servicePkgRecordService;

    @Autowired
    ReceiverValveMapper receiverValveMapper;
    public static final String split = ";";
    public static final String split_ = "-";
    //可偏移的毫秒值，范围为<=
    private final Integer offsetRangeConstant = 150000;
    private final Integer MaxRangeConstant = 600000;
    //需要匹配的key
    private String patternKey = Constants.WARNING_EQUIPMENT + ":*";

    public static final String CM_SERVICE_HOT_LINE = "cm_service_hot_line";

    @Value(value = "${gassafety.warnStrategy.switch}")
    private boolean sw;
    @Autowired
    RedisCacheExt redisUtil;

    @Autowired
    VccAuthoritiesProvider provider;

    @Autowired
    DeviceStateMapper deviceStateMapper;
    @Autowired
    DtuBindingOrderMapper dtuBindingOrderMapper;
    @Autowired
    ConsumerService consumerService;
    @Autowired
    CallTaskServiceStrategyImpl callTaskService;
    @Autowired
    RecordReceiverValveMapper recordReceiverValveMapper;

    /**
     * 扫描所有设备进行首次预警
     */
    public void warnStrategy(String imei, Integer deviceStatus,
                             Integer concentration) {
        log.info("warnStrategy--params:{},{},{}", imei, deviceStatus, concentration);
        try {
            String key = Constants.EQUIPMENT_WARNING_FIRST;
            Boolean acquire = redisUtil.setIfAbsent(key, String.valueOf(System.currentTimeMillis()), Constants.APPEAL_TIME_OUT);
            try {
                if (acquire) {
                    long beginTimeMillis = System.currentTimeMillis();
                    List<Map<String, Object>> dtuMaps = selectStrategyDtuList(imei);
                    long endTimeMillis = System.currentTimeMillis();
                    long diffTimeMillis = endTimeMillis - beginTimeMillis;
                    log.info("warnStrategy根据IMEI查询设备策略信息的新方法，开始毫秒数：{}，结束毫秒数：{}，耗时毫秒数：{}", beginTimeMillis, endTimeMillis, diffTimeMillis);
                    DeviceState deviceState = new DeviceState();
                    deviceState.setConcentration(concentration);
                    deviceState.setDeviceStatus(deviceStatus);
                    execute(dtuMaps, deviceState);
                }
            } catch (Exception e) {
                log.info("warnStrategy-error:{}", e);
            } finally {
                redisUtil.del(key);
            }
        } catch (Exception e) {
            log.error("warnStrategy-e:{}", e);
        }

    }

    private List<Map<String, Object>> selectStrategyDtuList(String imei) {
        List<Map<String, Object>> mapList = new ArrayList<>();
        // 查询IMEI
        QueryWrapper<Dtu> dtuQueryWrapper = new QueryWrapper<>();
        dtuQueryWrapper.lambda()
            .eq(Dtu::getIsDeleted,0)
            .eq(Dtu::getIMEI,imei)
            .gt(Dtu::getConsumerId,0);
        List<Dtu> dtuList = dtuMapper.selectList(dtuQueryWrapper);
        if (!CollectionUtils.isEmpty(dtuList)) {
            Dtu dtu = dtuList.get(0);
            // 查询客户
            QueryWrapper<Consumer> consumerQueryWrapper = new QueryWrapper<>();
            consumerQueryWrapper.lambda().eq(Consumer::getId, dtu.getConsumerId())
                .eq(Consumer::getSpId, dtu.getSpId())
                .eq(Consumer::getIsDeleted, Constants.IS_DELETED_FALSE);
            Consumer consumer = consumerMapper.selectOne(consumerQueryWrapper);
            if (consumer == null) {
                return mapList;
            }

            // 查询出当前企业下存在的，启用的，配置有效的策略， 根据策略对象类型降序方便遍历时跳出循环
            QueryWrapper<WarnStrategy> strategyQueryWrapper = new QueryWrapper<>();
            strategyQueryWrapper.lambda().eq(WarnStrategy::getIsDeleted,0)
                .eq(WarnStrategy::getSpId, dtu.getSpId())
                .eq(WarnStrategy::getIsDisabled,0)
                .and(lqw2 -> lqw2.ne(WarnStrategy::getLowType, -1)
                    .or().ne(WarnStrategy::getHighType, -1))
                .orderByDesc(WarnStrategy::getStrategyObj); //根据策略对象类型降序
            List<WarnStrategy> warnStrategys = warnStrategyMapper.selectList(strategyQueryWrapper);
            WarnStrategy validWarnStrategy = null;
            if (!CollectionUtils.isEmpty(warnStrategys)) {
                for (WarnStrategy warnStrategy : warnStrategys) {
                    if (warnStrategy.getStrategyObj() == 2) {
                        // 具体客户
                        List<Integer> consumerIds = Arrays.stream(warnStrategy.getStrategyObjValues().split(";"))
                            .filter(str -> !str.isEmpty()).map(str -> Integer.parseInt(str)).collect(Collectors.toList());
                        if (consumerIds.contains(dtu.getConsumerId())) {
                            validWarnStrategy = warnStrategy;
                            break;
                        }
                    } else if (warnStrategy.getStrategyObj() == 1 && !StringUtils.isEmpty(consumer.getIndustryType())) {
                        // 行业
                        List<String> industryTypeList = Arrays.stream(warnStrategy.getStrategyObjValues().split(";"))
                            .filter(str -> !str.isEmpty()).collect(Collectors.toList());
                        if (industryTypeList.contains(consumer.getIndustryType())) {
                            validWarnStrategy = warnStrategy;
                            break;
                        }
                    } else if (warnStrategy.getStrategyObj() == 0){
                        // 所有客户
                        validWarnStrategy = warnStrategy;
                        break;
                    }
                }

            }
            if (validWarnStrategy == null) {
                return mapList;
            }

            // 组装数据
            Map<String, Object> dtuMap = new HashMap<>();
            dtuMap.put("Id",dtu.getId());
            dtuMap.put("iMEI",dtu.getIMEI());
            dtuMap.put("sp_id",dtu.getSpId());
            dtuMap.put("equipment_type",dtu.getEquipmentType());

            dtuMap.put("low_report",validWarnStrategy.getLowReport());
            dtuMap.put("low_type",validWarnStrategy.getLowType());
            dtuMap.put("low_send_interval",validWarnStrategy.getLowSendInterval());
            dtuMap.put("low_report_interval",validWarnStrategy.getLowReportInterval());
            dtuMap.put("low_wx_interval",validWarnStrategy.getLowWxInterval());
            dtuMap.put("low_call_interval",validWarnStrategy.getLowCallInterval());

            dtuMap.put("high_report",validWarnStrategy.getHighReport());
            dtuMap.put("high_type",validWarnStrategy.getHighType());
            dtuMap.put("high_send_interval",validWarnStrategy.getHighSendInterval());
            dtuMap.put("high_report_interval",validWarnStrategy.getHighReportInterval());
            dtuMap.put("high_wx_interval",validWarnStrategy.getHighWxInterval());
            dtuMap.put("high_call_interval",validWarnStrategy.getHighCallInterval());
            dtuMap.put("check_device_state",validWarnStrategy.getCheckDeviceState());

            dtuMap.put("valve_info_id",dtu.getValveInfoId());
            dtuMap.put("equipment_model",dtu.getEquipmentModel());
            dtuMap.put("cust_type",consumer.getCustType());
            dtuMap.put("Industry_Type",consumer.getIndustryType());
            dtuMap.put("Name",consumer.getName());
            dtuMap.put("subs_code",consumer.getSubsCode());
            dtuMap.put("cust_name",consumer.getCustName());
            dtuMap.put("cust_address",consumer.getCustAddress());
            dtuMap.put("cust_phone",consumer.getCustPhone());
            mapList.add(dtuMap);

        }
        return mapList;
    }

    private boolean execute(List<Map<String, Object>> dtuMaps, DeviceState deviceState) {
        log.info("execute-param：{},deviceState:{}", JSONObject.toJSON(dtuMaps), JSONObject.toJSON(deviceState));
        if (!CollectionUtil.isEmpty(dtuMaps)) {
            //执行了删除缓存队列里的数据
            //判断是否触发预警
            boolean servicePackageModeSwitch = false;
            if (!dtuMaps.isEmpty() && null != dtuMaps.get(0).get("sp_id")) {
                servicePackageModeSwitch = businessNoticeService.getServicePackageSwitch(dtuMaps.get(0).get("sp_id").toString());
            }
            log.info("servicePackageModeSwitch:{}",servicePackageModeSwitch);
            for (Map<String, Object> dtuMap : dtuMaps) {
                log.info("strategy_obj:{}",dtuMap.get("strategy_obj").toString());
                if (!servicePackageModeSwitch && "3".equals(dtuMap.get("strategy_obj").toString())) {
                    continue;
                }
                Object iMEI = dtuMap.get("iMEI");
                //获取这个点位
                if (deviceState == null || deviceState.getDeviceStatus() == null)
                    deviceState = deviceStateMapper.selectByDeviceId(iMEI, dtuMap.get("sp_id"));
                if (deviceState == null) continue;
                Integer value = StringUtils.isEmpty(deviceState.getConcentration()) ? 0 : deviceState.getConcentration();
                log.info("execute-value:{}", value);
                String s = iMEI.toString();
                String subId = "";
                if (!s.contains(split_)) {
                    if (!"Gas_alarm_controller".equals(dtuMap.get("equipment_type"))) {
                        subId = "1-0";
                    } else {
                        continue;
                    }
                } else {
                    subId = "1-" + s.split(split_)[2];
                }
                log.info("execute-subId:{}", subId);
                String redisKey = Constants.WARNING_EQUIPMENT + ":" + (s.contains("-") ? iMEI : iMEI + "-" + subId);
                log.info("execute-redisKey:{}", redisKey);
                Map<String, Object> cacheMapOne = redisCache.getCacheMap(redisKey);
                log.info("execute-cacheMapOne:{}", JSONObject.toJSON(cacheMapOne));
                if (cacheMapOne != null && cacheMapOne.size() == 0) {
                    cacheMapOne = null;
                    log.info("execute-cacheMapOne2:{}", cacheMapOne);
                }
                warningRecordService.updateRecordStatusByImei(s);
                Integer checkDeviceState = 0;
                if( null!=dtuMap.get("check_device_state") ){
                    checkDeviceState = (Integer) dtuMap.get("check_device_state");
                }
                Integer status = deviceState.getDeviceStatus() == null ? 0 : deviceState.getDeviceStatus();
                if (status == 0) {
                    log.info("execute-设备已经离线:{}", (s.contains("-") ? iMEI : iMEI + "-" + subId));
                }
                //是否检验报警状态 0:否 1:校验
                if ( checkDeviceState == 1 && (status != 2 && status != 3 && status != 6) ) {
                    log.info("execute-是否检验报警状态:{},设备状态为未报警:{},{}",
                            checkDeviceState,
                            (s.contains("-") ? iMEI : iMEI + "-" + subId), 
                            status);
                    if( cacheMapOne != null ){
                        redisCache.deleteObject(Constants.WARNING_EQUIPMENT + ":" + (iMEI.toString().contains("-") ? iMEI : iMEI + "-" + subId));
                        //更新数据
                        warningRecordService.updateRecordStatus(iMEI + "", cacheMapOne.get("identificationCode") + "", 2);
                        //删除策略执行次数key
                        redisCache.deleteObject(Constants.ALARM_STRATEGY + s + dtuMap.get("sp_id"));
                        log.info("execute-删除队列中的key,原因设备状态不符合告警状态：{}", Constants.WARNING_EQUIPMENT + ":" + (iMEI.toString().contains("-") ? iMEI : iMEI + "-" + subId));
                    }
                    continue;
                }

                //检测是否预警
                String lowReport = dtuMap.get("low_report") + "";
                String highReport = dtuMap.get("high_report") + "";
                Integer lowType = Integer.parseInt(dtuMap.get("low_type") + "");
                Integer highType = Integer.parseInt(dtuMap.get("high_type") + "");
                Object highSendInterval = dtuMap.get("high_send_interval");
                Object highReportInterval = dtuMap.get("high_report_interval");
                Object lowSendInterval = dtuMap.get("low_send_interval");
                Object lowReportInterval = dtuMap.get("low_report_interval");
                Object highWxInterval = dtuMap.get("high_wx_interval");
                Object lowWxInterval = dtuMap.get("low_wx_interval");
                Object highCallInterval = dtuMap.get("high_call_interval");
                Object lowCallInterval = dtuMap.get("low_call_interval");
                Object highSmsMsgCode = dtuMap.get("high_sms_msg_code");
                Object highWxMsgCode = dtuMap.get("high_wx_msg_code");
                Object lowSmsMsgCode = dtuMap.get("low_sms_msg_code");
                Object lowWxMsgCode = dtuMap.get("low_wx_msg_code");
                long snowflakeId = SnowflakeUtil.getSnowflakeId();
                try {
                    boolean flag = true;
                    if (!StringUtils.isEmpty(lowReport) && NumberUtil.isNumber(lowReport)) {
                        if ((StringUtils.isEmpty(highReport) && Integer.parseInt(lowReport) <= value) ||
                                ((!StringUtils.isEmpty(highReport) && Integer.parseInt(lowReport) <= value &&
                                        Integer.parseInt(highReport) > value))) {
                            flag = false;
                            log.info("execute-低报:{}", iMEI);
                            if (cacheMapOne != null && cacheMapOne.size() > 0) return false;
                            dtuMap.put("sms_msg_code",lowSmsMsgCode);
                            dtuMap.put("wx_msg_code",lowWxMsgCode);
                            detailOpt(lowType, dtuMap, iMEI + "", subId, lowSendInterval,
                                    lowReportInterval, lowWxInterval, lowCallInterval, value, 1, snowflakeId);
                            log.info("execute-报警类型:{},imei:{}", "低报", iMEI);
                        }
                    }
                    if (!StringUtils.isEmpty(highReport) && NumberUtil.isNumber(highReport)) {
                        if (Integer.parseInt(highReport) <= value) {
                            flag = false;
                            log.info("execute-高报:{}", iMEI);
                            if (cacheMapOne != null && cacheMapOne.size() > 0) return false;
                            dtuMap.put("sms_msg_code",highSmsMsgCode);
                            dtuMap.put("wx_msg_code",highWxMsgCode);
                            //开始预警
                            detailOpt(highType, dtuMap, iMEI + "", subId, highSendInterval,
                                    highReportInterval, highWxInterval, highCallInterval, value, 2, snowflakeId);
                            log.info("execute-报警类型:{},imei:{}", "高报", iMEI);
                        }
                    }
                    log.info("execute-flag:{}", flag);  
                    if (flag && cacheMapOne != null) {
                        log.info("execute-iMEI:{}", iMEI);
                        redisCache.deleteObject(Constants.WARNING_EQUIPMENT + ":" + (iMEI.toString().contains("-") ? iMEI : iMEI + "-" + subId));
                        //更新数据
                        warningRecordService.updateRecordStatus(iMEI + "", cacheMapOne.get("identificationCode") + "", 2);
                        //删除策略执行次数key
                        redisCache.deleteObject(Constants.ALARM_STRATEGY + s + dtuMap.get("sp_id"));
                        log.info("execute-删除队列中的key,原因dtu不符合条件：{}", Constants.WARNING_EQUIPMENT + ":" + (iMEI.toString().contains("-") ? iMEI : iMEI + "-" + subId));
                    }
                    if (!flag){
                        break;
                    }
                } catch (Exception e) {
                    log.error("execute-error:{}", e);
                }
            }
        }
        return false;
    }


    private void route(int route, Map<String, Object> dtuMap, String iMEI, String subId, Object sendInterval,
                       Object reportInterval, Object wxInterval, Object callInterval, Integer value, int report, long snowflakeId,
                       String con, List<Map<String, Object>> list, Object strategyId, List<WarnStrategyExt> exts,
                       Map<String, Object> dataMap, Date date, Map<String, Object> assembleTemplate, List<String> openIds) {
        try {

            dtuMap.put("cust_name", StringUtils.isEmpty(dtuMap.get("cust_name")) ? dtuMap.get("custName") : dtuMap.get("cust_name"));
            dtuMap.put("subs_code", StringUtils.isEmpty(dtuMap.get("subs_code")) ? dtuMap.get("memberId") : dtuMap.get("subs_code"));

            //1本地消息中心 2 短信推送 3 微信模版消息 4机器人外呼
            if (PushTypeEnum.getPushTypes(null, 2).contains(route)) {
                log.info("route----start:{}", "发送短信");
                List<WarnStrategyExt> collect = exts.stream().filter(warnStrategyExt -> {
                    return warnStrategyExt.getPushType() == 1;
                }).collect(Collectors.toList());

                //获取间隔对应值
                Map<String, Object> res = sendMessage(sendInterval, list, collect, dataMap, date,
                        (Map<String, Object>) assembleTemplate.get("param"), dtuMap.get("sp_id") + "", subId.equals("1-0") ? iMEI : (iMEI + "-" + subId), value, report, con, strategyId,
                        1, snowflakeId, assembleTemplate.get("SMSMessage") + "",
                        iMEI, dtuMap.get("cust_name") + "(" + dtuMap.get("subs_code") + ")");
                log.info("route----res:{}", JSONObject.toJSONString(res));
                if (!res.get("res").equals("no")) {
                    dataMap.put("count_m", 1);
                }
            }
            if (PushTypeEnum.getPushTypes(null, 1).contains(route)) {
                log.info("route----start:{}", "发送本地消息");
                reportMessage(reportInterval, dataMap, date);
                //封装消息数据
                String imei = iMEI;
                if (dtuMap.get("equipment_type").equals("Gas_alarm_controller")) {
                    imei = imei + "-" + subId;
                }
                log.info("route----本地消息:{}", imei);
                sendLocalMessage(dtuMap, imei, subId, value, con);
                saveWarningRecord(dtuMap.get("sp_id") + "", imei, value, report, con, strategyId,
                        0, date, 2, snowflakeId, 0, assembleTemplate.get("localMessage") + "",
                        iMEI, null, null, null, -1, null);
                dataMap.put("count_r", 1);

            }
            int type = 0;
            if (PushTypeEnum.getPushTypes(null, 3).contains(route)) {
                List<String> phones = new ArrayList<>();
                log.info("route----start:{}", "发送微信消息");

                if (report == 1) {
                    String lowWxPhones = dtuMap.get("low_wx_phones") + "";
                    if (!StringUtils.isEmpty(lowWxPhones) && lowWxPhones.contains(split)) {
                        phones = new ArrayList<>(Arrays.asList(lowWxPhones.split(StrategyServiceImpl.split)));
                    }
                } else {
                    String highWxPhones = dtuMap.get("high_wx_phones") + "";
                    if (!StringUtils.isEmpty(highWxPhones) && highWxPhones.contains(split)) {
                        phones = new ArrayList<>(Arrays.asList(highWxPhones.split(StrategyServiceImpl.split)));
                    }
                }
                log.info("route-wx-phones:{}", JSONObject.toJSONString(phones));
                //获取openIds
                if (!CollectionUtil.isEmpty(openIds) || !CollectionUtil.isEmpty(phones)) {
                    //发送微信消息
                    //调用外部微信接口
                    Map<String, Object> resWx = sendWxMessage(wxInterval, date, (Map<String, Object>) assembleTemplate.get("wxParam"), dataMap, dtuMap,
                            subId.equals("1-0") ? iMEI : (iMEI + "-" + subId), value, report, con, strategyId,
                            3, snowflakeId, assembleTemplate.get("wxMessage") + "",
                            iMEI, openIds, phones, type);
                    log.info("route----resWx:{}", JSONObject.toJSONString(resWx));
                    if (!resWx.get("res").equals("no")) {
                        dataMap.put("count_w", 1);
                    }
                }
                if (CollectionUtil.isEmpty(openIds)) {
                    if (!StringUtils.isEmpty(dtuMap.get("subs_code"))) {
                        LambdaQueryWrapper<CustomerSubs> lambdaQueryWrapper = new LambdaQueryWrapper<>();
                        lambdaQueryWrapper.eq(CustomerSubs::getIsDeleted, 0)
                                .eq(CustomerSubs::getBandingStatus, 1)
                                .eq(CustomerSubs::getSubsCode, dtuMap.get("subs_code"));
                        if (!CollectionUtil.isEmpty(customerSubsMapper.selectList(lambdaQueryWrapper))) {
                            //调用外部微信接口
                            type = -1;
                            Map<String, Object> resWx = sendWxMessage(wxInterval, date, (Map<String, Object>) assembleTemplate.get("wxParam"), dataMap, dtuMap,
                                    subId.equals("1-0") ? iMEI : (iMEI + "-" + subId), value, report, con, strategyId,
                                    3, snowflakeId, assembleTemplate.get("wxMessage") + "",
                                    iMEI, new ArrayList<>(), new ArrayList<>(), type);
                            log.info("route----resWx:{}", JSONObject.toJSONString(resWx));
                            if (!resWx.get("res").equals("no")) {
                                dataMap.put("count_w", 1);
                            }
                        }
                    }
                }
            }

            if (PushTypeEnum.getPushTypes(null, 4).contains(route)) {
                //发送外呼消息
                log.info("route----start:{}", "发送外呼消息");
                log.info("route----exts:{}", JSONObject.toJSONString(exts));
                List<WarnStrategyExt> collect = exts.stream().filter(warnStrategyExt -> {
                    return warnStrategyExt.getPushType() == 2;
                }).collect(Collectors.toList());
                log.info("route----ext:{}", JSONObject.toJSONString(collect));
                //获取间隔对应值
                Map<String, Object> res = callMessage(callInterval, list, collect, dataMap, date,
                        dtuMap.get("sp_id") + "", subId.equals("1-0") ? iMEI : (iMEI + "-" + subId),
                        value, report, con, strategyId,
                        4, snowflakeId,
                        iMEI, dtuMap.get("cust_name") + "(" + dtuMap.get("subs_code") + ")", dtuMap.get("equipment_type") + "");
                log.info("route----res:{}", JSONObject.toJSONString(res));
                if (!res.get("res").equals("no")) {
                    dataMap.put("count_c", 1);
                }
            }
        } catch (Exception e) {
            log.error("route-error:{}", e);
        }
    }


    private void pushWx(Map<String, Object> param, String spId, String iMEI, Integer value, int report,
                        String con, Object strategyId, Date date, int sendType,
                        long snowflakeId, String content, String supIMEI, List<String> openIds
            , String custName, String custCode, List<String> phones, int type) {

        log.info("pushWx-wx-phones:{}", JSONObject.toJSONString(phones));
        String orgCode = companyService.getOrgCode(spId, con);
        log.info("pushWx-wx-orgCode:{}", JSONObject.toJSONString(orgCode));

        String msgCode = Constants.WARN__WX_STRATEGY;
        if (!StringUtils.isEmpty(param.get("wxMsgCode"))) {
            msgCode = param.get("wxMsgCode").toString();
        }
        param.remove("wxMsgCode");

        Map<String, Object> sms = sendMessageService
                .sendSms(sendMessageService
                                .getRequestParam(null
                                        , msgCode, orgCode
                                        , param, "wxtpl", openIds, type == -1 ? custCode : null, phones, 0)
                        , "");
        String dataStr = (null==sms || null==sms.get("data"))?"":JSONObject.toJSONString(sms.get("data"));
        if (sms.get("result").equals(true)) {
            //发送成功
            String errorMsg = "发送成功";
            if (sms.get("data") != null) {
                HashMap<String, Object> req = new HashMap<>();
                req.put("ids", sms.get("data"));
                req.put("orgCode", orgCode);
                try {
                    Thread.sleep(2000L);
                    Map<String, Object> resMap = sendMessageService.subTaskDetail(req, "");
                    //延迟获取数据
                    errorMsg = resMap != null ? (String) resMap.get("errorMsg") : "";
                } catch (InterruptedException e) {
                    log.error("subTaskDetail-error:{}", e);
                }

                log.info("sendWxMessageAgain-微信消息发送人:{},{}发送结果:{}"
                        , JSONObject.toJSONString(openIds), JSONObject.toJSONString(phones),
                        JSONObject.toJSONString(errorMsg));
            }
            saveWarningRecord(spId, iMEI, value, report, con, strategyId,
                    0, date, sendType, snowflakeId, !StringUtils.isEmpty(errorMsg) ? 1 : 0, content,
                    supIMEI, errorMsg, dataStr, !CollectionUtil.isEmpty(phones) ? phones.get(0) : "", 2, custName + "(" + custCode + ")");
        } else {
            String errorMsg = (String)sms.get("errMsg");
            saveWarningRecord(spId, iMEI, value, report, con, strategyId,
                    0, date, sendType, snowflakeId, !StringUtils.isEmpty(errorMsg) ? 1 : 0, content,
                    supIMEI, errorMsg, dataStr, !CollectionUtil.isEmpty(phones) ? phones.get(0) : "", 2, custName + "(" + custCode + ")");
        }
    }


    private void detailOpt(Integer type, Map<String, Object> dtuMap, String iMEI, String subId,
                           Object sendInterval, Object reportInterval, Object wxInterval, Object callInterval, Integer value, int report
            , long snowflakeId) {
        if (StringUtils.isEmpty(sendInterval + "") &&
                StringUtils.isEmpty(reportInterval + "") &&
                StringUtils.isEmpty(wxInterval + "")) return;
        String con = dtuMap.get("ConsumerId") + "";
        List<Map<String, Object>> list = contactsMapper.selectInfo(con);
        Object strategyId = dtuMap.get("strategyId");
        if (strategyId != null) {
            QueryWrapper<WarnStrategyExt> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(WarnStrategyExt::getIsDeleted, 0)
                    .eq(WarnStrategyExt::getStrategyId, strategyId)
                    .eq(WarnStrategyExt::getType, report)
                    .orderByAsc(WarnStrategyExt::getSort);
            List<WarnStrategyExt> exts = warnStrategyExtMapper.selectList(queryWrapper);
            if (!CollectionUtil.isEmpty(exts) || type != 2) {
                //缓存, 机器iMEI为key，
                Map<String, Object> dataMap = new HashMap<>();
                dataMap.put("count", 1);
                dataMap.put("level", CollectionUtil.isEmpty(exts) ? 0 : exts.get(0).getPushLevel());//发送级别
                dataMap.put("ruleCount", exts.size());//当前规则总数
                dataMap.put("path", dtuMap.get("Path"));
                dataMap.put("strategyId", strategyId);
                dataMap.put("consumerId", con);
                dataMap.put("iMEI", iMEI.contains("-") ? iMEI : iMEI + "-" + subId);
                dataMap.put("identificationCode", snowflakeId);
                dataMap.put("type", report);//1低报
                dataMap.put("pushWay", type);

                String smsMsgCode = StringUtils.isEmpty(dtuMap.get("sms_msg_code"))?"":dtuMap.get("sms_msg_code").toString();
                String wxMsgCode = StringUtils.isEmpty(dtuMap.get("wx_msg_code"))?"":dtuMap.get("wx_msg_code").toString();
                dataMap.put("smsMsgCode",smsMsgCode);
                dataMap.put("wxMsgCode",wxMsgCode);

                //开始预警
                Date date = new Date();
                QueryWrapper<BusinessNotice> query = new QueryWrapper<>();
                query.lambda().or().eq(BusinessNotice::getIsDeleted, 0)
                        .eq(BusinessNotice::getSpId, dtuMap.get("sp_id"))
                        .eq(BusinessNotice::getParamCode, CM_SERVICE_HOT_LINE);
                List<BusinessNotice> r = noticeMapper.selectList(query);
                String phone = "";
                if (!CollectionUtil.isEmpty(r)) {
                    phone = r.get(0).getParamValue();
                }
                //短信
                String imei = iMEI;
                if (dtuMap.get("equipment_type").equals("Gas_alarm_controller")) {
                    imei = imei + "-" + subId;
                }

                String equipmentType = null==dtuMap.get("equipment_type")?"":dtuMap.get("equipment_type").toString();
                String installationPosition = null==dtuMap.get("installation_position")?"":dtuMap.get("installation_position").toString();
                String custAddress = null==dtuMap.get("cust_address")?"":dtuMap.get("cust_address").toString();
                String consumerName = null==dtuMap.get("consumerName")?"":dtuMap.get("consumerName").toString();
                String equipmentName = null==dtuMap.get("equipmentName")?"":dtuMap.get("equipmentName").toString();
                String custName = null==dtuMap.get("custName")?"":dtuMap.get("custName").toString();
                if( StringUtils.isEmpty(custName) ){
                    custName = null==dtuMap.get("cust_name")?"":dtuMap.get("cust_name").toString();
                }
                String subsCode= null==dtuMap.get("subs_code")?"":dtuMap.get("subs_code").toString();
                String equipmentManufacturer = null==dtuMap.get("equipment_manufacturer")?"":dtuMap.get("equipment_manufacturer").toString();

                AssembleTemplateDTO assembleTemplateDTO = new AssembleTemplateDTO();
                assembleTemplateDTO.setValue(value);
                assembleTemplateDTO.setReport(report);
                assembleTemplateDTO.setPhone(phone);
                assembleTemplateDTO.setImei(imei);
                assembleTemplateDTO.setEquipmentType(equipmentType);
                assembleTemplateDTO.setInstallationPosition(installationPosition);
                assembleTemplateDTO.setConsumerName(consumerName);
                assembleTemplateDTO.setEquipmentName(equipmentName);
                assembleTemplateDTO.setCustAddress(custAddress);
                assembleTemplateDTO.setConsumerId(con);
                assembleTemplateDTO.setCustName(custName);
                assembleTemplateDTO.setSubsCode(subsCode);
                assembleTemplateDTO.setEquipmentManufacturer(equipmentManufacturer);
                assembleTemplateDTO.setSpId(dtuMap.get("sp_id").toString());
                assembleTemplateDTO.setSmsMsgCode(smsMsgCode);
                assembleTemplateDTO.setWxMsgCode(wxMsgCode);

                Map<String, Object> assembleTemplate = getAssembleTemplate(assembleTemplateDTO);
                log.info("execute-assembleTemplate:{}", JSONObject.toJSON(assembleTemplate));
                String e = "";
                if (iMEI.contains("-")) {
                    e = iMEI.split("-")[0];
                } else {
                    e = iMEI;
                }
//                List<String> openIds = devicebindingService.selectDevicebinding(e);
                List<String> openIds = new ArrayList<>();
                log.info("execute-openIds:{}", JSONObject.toJSON(openIds));
                //发送本地消息和短信微信、外呼
                route(type, dtuMap, iMEI, subId, sendInterval, reportInterval, wxInterval, callInterval, value, report, snowflakeId, con, list, strategyId, exts, dataMap, date, assembleTemplate, openIds);
                log.info("execute-cacheMap:{}", JSONObject.toJSON(dataMap));
                redisCache.setCacheMap(Constants.WARNING_EQUIPMENT + ":" + (iMEI.contains("-") ? iMEI : iMEI + "-" + subId), dataMap);
//                redisTemplate.expire(Constants.WARNING_EQUIPMENT + ":" + (iMEI.contains("-") ? iMEI : iMEI + "-" + subId), 60, TimeUnit.SECONDS);

            }


        }

    }


    private boolean reportMessage(Object reportInterval, Map<String, Object> dataMap, Date date) {
        boolean result = true;
        try {
            if (!StringUtils.isEmpty(reportInterval) && ("no".equals(reportInterval)
                    || !reportInterval.toString().contains("_"))) return false;
            //发送本地消息
            DateTime nextReportTime = DateUtil.offsetMinute(date,
                    Integer.parseInt(reportInterval.toString().split("_")[0]));
            dataMap.put("nextReportTime", nextReportTime.getTime());
        } catch (Exception e) {
            log.error("reportMessage-error:{}", e);
        }
        return result;
    }

    private Map<String, Object> getAssembleTemplate(AssembleTemplateDTO assembleTemplate) {
        String orgCode = companyService.getOrgCode(assembleTemplate.getSpId(), (String) assembleTemplate.getConsumerId());
        assembleTemplate.setOrgCode(orgCode);

        Object value = assembleTemplate.getValue();
        int report = assembleTemplate.getReport();
        String phone = assembleTemplate.getPhone();
        String imei = assembleTemplate.getImei();
        String equipmentType = assembleTemplate.getEquipmentType();
        String installationPosition = assembleTemplate.getInstallationPosition();
        String consumerName = assembleTemplate.getConsumerName();
        String equipmentName = assembleTemplate.getEquipmentName();
        String custAddress = assembleTemplate.getCustAddress();
        Object consumerId = assembleTemplate.getConsumerId();
        String custName = assembleTemplate.getCustName();
        String subsCode = assembleTemplate.getSubsCode();
        String equipmentManufacturerName = equipmentService.getEquipmentManufacturerName(
                assembleTemplate.getEquipmentManufacturer(),
                assembleTemplate.getSpId()
        );

        QueryWrapper<DtuBindingOrder> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.lambda().or().eq(DtuBindingOrder::getIsDeleted, 0)
                .eq(DtuBindingOrder::getConsumerId, consumerId);
        List<DtuBindingOrder> dtuBindingOrders = dtuBindingOrderMapper.selectList(orderQueryWrapper);
        String userID = "";
        String name = "";
        String address = "";
        if (!CollectionUtil.isEmpty(dtuBindingOrders)) {
            DtuBindingOrder dtuBindingOrder = dtuBindingOrders.get(0);
            address = StringUtils.isEmpty(dtuBindingOrder.getAddress()) ? dtuBindingOrder.getRealAddress() : dtuBindingOrder.getAddress();
            userID = dtuBindingOrder.getMemberId();
            name = dtuBindingOrder.getCustName();
        } else {
            address = custAddress;
        }
        custName = custName == null ? "" : custName;
        subsCode = subsCode == null ? "" : subsCode;
        equipmentName = StringUtils.isEmpty(equipmentName) ? "" : equipmentName;
        Map<String, Object> resultMap = new HashMap<>();
        String format = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");

        Map<String, Object> param = new HashMap<>();
        param.put("Time", format);
        param.put("value", value + "%LEL");
        param.put("position", installationPosition);
        param.put("Equipmenttype", EquipmentTypeConst.equipmentTypeMaps.get(equipmentType));
        param.put("IMEI", imei);
        param.put("Equipment_status", "报警");
        param.put("phone", phone);
        param.put("UserID", userID);
        param.put("Name", name);
        param.put("address", address);
        param.put("EquipmentName", equipmentName);
        param.put("subsName", custName);
        param.put("factoryName",equipmentManufacturerName);
        param.put("smsMsgCode",assembleTemplate.getSmsMsgCode());
        param.put("CustomerName",assembleTemplate.getConsumerName());
        String SMSMessage = sendMessageService.getSmsContent(Constants.WARN_STRATEGY,param,assembleTemplate);


        //微信模板消息 WARNING_WX_MESSAGES
        String wxAddress = address.length() < 20 ? address : address.substring(0, 20);
        String subsName = custName.length() < 20 - subsCode.length() ? custName : custName.substring(0, 15 - subsCode.length()) + "...";

        Map<String, Object> wxParam = new HashMap<>();
        wxParam.put("Time", format);
        wxParam.put("value", value + "%LEL");
        wxParam.put("position", installationPosition);
        wxParam.put("Equipmenttype", EquipmentTypeConst.equipmentTypeMaps.get(equipmentType));
        wxParam.put("IMEI", imei);
        wxParam.put("Equipment_status", "报警");
        wxParam.put("phone", phone);
        wxParam.put("EquipmentName", equipmentName);
        wxParam.put("Name", name);
        wxParam.put("UserID", userID);
        wxParam.put("address", wxAddress);
        wxParam.put("subsName", subsName);
        wxParam.put("subsCode", subsCode);
        wxParam.put("factoryName",equipmentManufacturerName);
        wxParam.put("wxMsgCode",assembleTemplate.getWxMsgCode());
        wxParam.put("CustomerName",assembleTemplate.getConsumerName());
        String wxMessage = sendMessageService.getWxContent(Constants.WARN__WX_STRATEGY,wxParam,assembleTemplate);

        //本地消息
        String localMessage = Constants.WARNING_LOCAL_MESSAGES.replace("type", report == 1 ? "低报" : "高报")
                .replace("time", DateUtil.format(new Date(), "yyyy年MM月dd日 HH:mm:ss"))
                .replace("name", consumerName )
                .replace("num", imei)
                .replace("value", value+"");


        resultMap.put("SMSMessage", SMSMessage);
        resultMap.put("param", param);
        resultMap.put("wxParam", wxParam);
        resultMap.put("localMessage", localMessage);
        resultMap.put("wxMessage", wxMessage);
        log.info("localMessage:{}SMSMessage:{}wxMessage:{}", localMessage, param, wxParam);
        return resultMap;
    }

    //存储报警记录
    public void saveWarningRecord(String spId, String iMEI,
                                  Integer value, int report, String con, Object strategyId,
                                  Integer level, Date date, int sendType, long snowflakeId, int sendResult,
                                  String content, String supIMEI, Object errorMsg,
                                  String receiptCode, String telephone, int type, String info) {
        if (iMEI.contains("-")){
            String[] split = iMEI.split("-");
            if (split.length>=3) iMEI=split[0]+"-"+split[1]+"-"+split[2];
        }
        WarningRecord warningRecord = new WarningRecord();
        warningRecord.setConsumerId(con);
        warningRecord.setStartTime(date);
        warningRecord.setWarningStartTime(date);
        warningRecord.setTriggerRuleId(strategyId + "");
        warningRecord.setIMEI(iMEI);
        warningRecord.setTaskIdentificationCode(snowflakeId + "");
        warningRecord.setConcentration(value + "");
        warningRecord.setType(report);
        warningRecord.setSendType(sendType);
        warningRecord.setObjLevel(level);
        warningRecord.setSpId(spId);
        warningRecord.setSendResult(sendResult);
        warningRecord.setContent(content);
        warningRecord.setReceiptCode(receiptCode);
        warningRecord.setNotifyObjInfo(info);
        warningRecord.setNotifyObjType(type);
        warningRecord.setPushPhone(telephone);
        warningRecord.setSupIMEI(supIMEI);
        warningRecord.setNotifyFrom(0);
        warningRecord.setRemark(!StringUtils.isEmpty(errorMsg) ? errorMsg + "" : "发送成功");

        log.info("saveWarningRecord:{}", JSONObject.toJSONString(warningRecord));
        warningRecordMapper.insert(warningRecord);
    }

    //发送本地消息
    private void sendLocalMessage(Map<String, Object> dtuMap, String iMEI, String subId, Integer value, String con) {
        log.info("sendLocalMessage-dtuMap:{}", JSONObject.toJSONString(dtuMap));

        //根据imei和用户id获得联系人姓名
        String contactName = "";
        if (StringUtil.isNotEmpty(dtuMap.get("member_id") + "")) {
            QueryWrapper<DtuBindingOrder> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(DtuBindingOrder::getMemberId, dtuMap.get("member_id") + "")
                    .eq(DtuBindingOrder::getDeviceId, iMEI)
                    .eq(DtuBindingOrder::getIsDeleted, Constants.IS_DELETED_FALSE);
            List<DtuBindingOrder> orderList = dtuBindingOrderMapper.selectList(queryWrapper);
            log.info("sendLocalMessage-orderList:{}", JSONObject.toJSONString(orderList));
            try {
                contactName = orderList.get(0).getCustName();
            } catch (Exception e) {
                log.error("sendLocalMessage-error:{}", e);
            }
        }
        contactName = contactName == null ? "" : contactName;
        JSONObject object = new JSONObject();
        Map<String, Object> messageMap = new HashMap<>();
        messageMap.put("notifyReason", "WarnStrategy");
        messageMap.put("notifyName", "设备触发报警策略");
        messageMap.put("notifyTime", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        messageMap.put("imei", iMEI);
        messageMap.put("installationPosition", dtuMap.get("installation_position"));
        messageMap.put("equipmentTypeName", EquipmentTypeConst.equipmentTypeMaps.get(dtuMap.get("equipment_type")));
        messageMap.put("xlel", value);
        messageMap.put("consumerId", con);
        messageMap.put("pkgId", dtuMap.get("pkg_id"));
        messageMap.put("custName", dtuMap.get("cust_name"));
        messageMap.put("subsCode", dtuMap.get("subs_code"));
        messageMap.put("isSystem", true);
        messageMap.put("isPop", true);
        messageMap.put("memberId", dtuMap.get("member_id"));
        messageMap.put("contactName", contactName);
        messageMap.put("equipmentFrom", dtuMap.get("equipment_from"));
        if (Integer.parseInt(dtuMap.get("equipment_from") + "") == 1) {
            QueryWrapper<ReceiverValve> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().or().eq(ReceiverValve::getIsDeleted, 0)
                    .eq(ReceiverValve::getDeviceId, iMEI);
            List<ReceiverValve> receiverValves = receiverValveMapper.selectList(queryWrapper);
            log.info("job-receiverValves:{}", JSON.toJSONString(receiverValves));
            if (!CollectionUtil.isEmpty(receiverValves)) {
                ReceiverValve receiverValve = receiverValves.get(0);
                messageMap.put("valveStatus", receiverValve.getValveStatus() == 0 ? "正常" : "关闭");
                messageMap.put("receiverStatus", receiverValve.getReceiverStatus() == 0 ? "离线" : "正常");

            }
            messageMap.put("phone", dtuMap.get("Phone"));
        }
        object.put("spId", dtuMap.get("sp_id"));
        object.put("message", messageMap);
        //发送本地消息
        log.info("sendLocalMessage-first-object:{}", JSONObject.toJSONString(object));
        sendMessageService.sendLocalSms(object, dtuMap.get("sp_id") + "");
    }

    private Map<String, Object> sendWxMessage(Object sendInterval, Date date,
                                              Map<String, Object> param, Map<String, Object> dataMap, Map<String, Object> dtuMap
            , String iMEI,
                                              Integer value, int report, String con, Object strategyId,
                                              int sendType, long snowflakeId,
                                              String content, String supIMEI, List<String> openIds, List<String> phones, int type) {
        Map<String, Object> res = null;
        try {
            res = new HashMap<>();
            res.put("res", true);
            if (!StringUtils.isEmpty(sendInterval) && ("no".equals(sendInterval)
                    || !sendInterval.toString().contains("_"))) {
                res.put("res", "no");
                return res;
            }

            if (!CollectionUtil.isEmpty(phones)) {
                phones.forEach(s -> {
                    log.info("sendWxMessage-wx-phones:{}", JSONObject.toJSONString(new ArrayList<>(Arrays.asList(new String[]{s}))));
                    pushWx(param, dtuMap.get("sp_id") + "", iMEI, value, report, con, strategyId, date, sendType, snowflakeId, content, supIMEI, openIds,
                            dtuMap.get("cust_name") + "", dtuMap.get("subs_code") + "",
                            new ArrayList<>(Arrays.asList(new String[]{s})), type);
                });
            } else {
                pushWx(param, dtuMap.get("sp_id") + "", iMEI, value, report, con, strategyId, date, sendType, snowflakeId, content, supIMEI, openIds,
                        dtuMap.get("cust_name") + "", dtuMap.get("subs_code") + "",
                        new ArrayList<>(), type);
            }


            DateTime nextSendTime = DateUtil.offsetMinute(date,
                    Integer.parseInt(sendInterval.toString().split("_")[0]));
            dataMap.put("nextWxInterval", nextSendTime.getTime());
        } catch (Exception e) {
            log.error("sendWxMessage-error:{}", e);
        }
        return res;
    }

    private Map<String, Object> sendMessage(Object
                                                    sendInterval, List<Map<String, Object>> list, List<WarnStrategyExt> exts
            , Map<String, Object> dataMap, Date date, Map<String, Object> param,
                                            String spId, String iMEI,
                                            Integer value, int report, String con, Object strategyId,
                                            int sendType, long snowflakeId,
                                            String content, String supIMEI, String info) {
        Map<String, Object> res = null;
        try {
            res = new HashMap<>();
            res.put("res", true);
            res.put("receiptCode", "");
            if (!StringUtils.isEmpty(sendInterval) && ("no".equals(sendInterval)
                    || !sendInterval.toString().contains("_"))) {
                res.put("res", "no");
                return res;
            }
            Map<String, String> s = sendSms(list, exts.get(0), param, spId, iMEI,
                    value, report, con, strategyId, sendType, snowflakeId, content, supIMEI
                    , date, info);

            res.put("errorMsg", s.get("errorMsg"));
            if (!StringUtils.isEmpty(s.get("receiptCode"))) res.put("receiptCode", s.get("receiptCode"));
            dataMap.put("phone", s);//实际发送手机号,和实际发送级别绑定
            DateTime nextSendTime = DateUtil.offsetMinute(date,
                    Integer.parseInt(sendInterval.toString().split("_")[0]));
            dataMap.put("nextSendTime", nextSendTime.getTime());
        } catch (Exception e) {
            log.error("sendMessage-error:{}", e);
        }
        return res;
    }


    private Map<String, Object> callMessage(Object
                                                    callInterval, List<Map<String, Object>> list, List<WarnStrategyExt> exts
            , Map<String, Object> dataMap, Date date,
                                            String spId, String iMEI,
                                            Integer value, int report, String con, Object strategyId,
                                            int sendType, long snowflakeId,
                                            String supIMEI, String info, String dtuType) {
        Map<String, Object> res = null;
        try {
            res = new HashMap<>();
            res.put("res", true);
            if (!StringUtils.isEmpty(callInterval) && ("no".equals(callInterval)
                    || !callInterval.toString().contains("_"))) {
                res.put("res", "no");
                return res;
            }
            callSms(list, exts.get(0), spId, iMEI,
                    value, report, con, strategyId, sendType, snowflakeId, supIMEI
                    , date, info, dtuType);
            DateTime nextSendTime = DateUtil.offsetMinute(date,
                    Integer.parseInt(callInterval.toString().split("_")[0]));
            dataMap.put("nextCallTime", nextSendTime.getTime());
        } catch (Exception e) {
            log.error("callMessage-error:{}", e);
        }
        return res;
    }

    private void callSms(List<Map<String, Object>> list, WarnStrategyExt ext,
                         String spId, String iMEI,
                         Integer value, int report, String con, Object strategyId,
                         int sendType, long snowflakeId,
                         String supIMEI, Date date, String info, String dtuType) {
        Map<String, Integer> objectTypeMap = new HashMap<>();
        Set<String> phones = new HashSet<>();
        try {
            String pushStaffs = ext.getPushStaffs();
            if (!StringUtils.isEmpty(pushStaffs)) {
                //走企业联系人
                String[] split = pushStaffs.split(this.split);
                for (String s : split) {
                    //获取对应手机号
                    String orgCode = companyService.getOrgCode(spId, con);
                    log.info("callSms-员工:{}", JSONObject.toJSONString(s));
                    cn.hutool.json.JSONObject staffs = provider.getStaffs(s, orgCode, "", 1, 10);
                    log.info("callSms-staffs:{}", JSONObject.toJSONString(staffs));
                    if (staffs != null && staffs.getJSONArray("datas") != null) {
                        cn.hutool.json.JSONObject datas = staffs.getJSONArray("datas").getJSONObject(0);
                        if (datas != null) {
                            String telephone = datas.getStr("phone");
                            if (!StringUtils.isEmpty(telephone)) {
                                phones.add(telephone);
                                objectTypeMap.put(telephone, 1);
                            }
                        }
                    } else {
                        continue;
                    }

                }
            }
            log.info("callSms-发送手机号:{}", phones);
            Integer pushLevel = ext.getPushLevel();
            log.info("callSms-list:{}", JSONObject.toJSONString(list));
            if (pushLevel != null || pushLevel != 0) {
                log.info("callSms-pushLevel:{}", JSONObject.toJSONString(pushLevel));
                //走客户联系人
                if (!CollectionUtil.isEmpty(list)) {
                    List<Integer> objs = new ArrayList<>();
                    list.forEach(stringObjectMap -> {
                        objs.add(Integer.parseInt(stringObjectMap.get("level") + ""));
                    });
                    if (!objs.contains(pushLevel)) {
                        List<Map<String, Object>> listCopy = new ArrayList<>();
                        for (Map<String, Object> map : list) {
                            if (pushLevel > Integer.parseInt(map.get("level") + "")) {
                                listCopy.add(map);
                            }
                        }
                        if (CollectionUtil.isEmpty(listCopy)) {
                            log.info("callSms-pushLevel，此级别没有合适的下级发送人：{}，客户id:{}"
                                    , pushLevel, con);
                        } else {
                            listCopy.sort((o1, o2) -> {
                                return -Integer.parseInt(o1.get("level") + "")
                                        + Integer.parseInt(o2.get("level") + "");
                            });
                            pushLevel = Integer.parseInt(listCopy.get(0).get("level") + "");
                        }
                    }

                    for (Map<String, Object> stringObjectMap : list) {
                        log.info("callSms-level:{}", Integer.parseInt(stringObjectMap.get("level") + ""));
                        log.info("callSms-pushLevel:{}", pushLevel);
                        if (Integer.parseInt(stringObjectMap.get("level") + "")
                                == pushLevel || pushLevel.equals(stringObjectMap.get("level"))) {
                            String telephone = stringObjectMap.get("telephone") + "";
                            if (!StringUtils.isEmpty(telephone)) {
                                phones.add(telephone);
                                log.info("callSms-pushLevel-发送级别手机号:{},{}"
                                        , telephone, JSONObject.toJSONString(stringObjectMap));
                                objectTypeMap.put(telephone, 0);
                            } else {
                                pushLevel = pushLevel + 1;
                            }
                        }
                    }
                }
            }
            log.info("callSms-发送手机号:{}", phones);

            //额外手机号：
            String callPhones = ext.getCallPhones();
            log.info("callSms-ext:{}", JSONObject.toJSONString(ext));
            if (!StringUtils.isEmpty(callPhones)) {
                String[] split = callPhones.split(this.split);
                for (String s : split) {
                    phones.add(s);
                    objectTypeMap.put(s, 3);
                }
            }
            log.info("callSms-发送手机号:{}", phones);
            if (!CollectionUtils.isEmpty(phones)) {
                if ("Gas_alarm_controller".equals(dtuType) && iMEI.contains("-")) {
                    iMEI = iMEI.split("-")[0];
                }
                Map<String, Object> map = callTaskService.sendCallTask(spId, phones, iMEI,null,null);
                String errMsg = null==map.get("errMsg")?"":map.get("errMsg").toString();
                callTaskService.saveCallList((JSONArray) map.get("data"), (Map<String, Object>) map.get("dtuInfos"),
                        (Map<String, Object>) map.get("paramMap"),
                        (List<String>) map.get("phoneList"), spId, iMEI, value, report, con, strategyId, pushLevel, date,
                        sendType, snowflakeId, StringUtils.isEmpty(errMsg)?2:1, iMEI, info, objectTypeMap, null, (String) map.get("robotContent"),
                        errMsg
                );
            }
        } catch (Exception e) {
            log.error("callSms-error:{}", e);
        }
    }


    private Map<String, String> sendSms(List<Map<String, Object>> list, WarnStrategyExt ext, Map<String, Object> param,
                                        String spId, String iMEI,
                                        Integer value, int report, String con, Object strategyId,
                                        int sendType, long snowflakeId,
                                        String content, String supIMEI, Date date, String info) {
        log.info("sendSms-param:{},{}", JSONObject.toJSONString(list), JSONObject.toJSONString(ext));
        //1.1增加企业员工
        Map<String, String> sendSms = new HashMap<>();
        AtomicReference<String> phoneAtomic = new AtomicReference<>();
        try {
            String pushStaffs = ext.getPushStaffs();
            if (!StringUtils.isEmpty(pushStaffs)) {
                //走企业联系人
                String[] split = pushStaffs.split(this.split);
                for (String s : split) {
                    //获取对应手机号
                    String orgCode = companyService.getOrgCode(spId, con);
                    String jobInfo = "";
                    String telephone = "";
                    String staffName = "";
                    log.info("send-Sms-员工:{}", JSONObject.toJSONString(s));
                    cn.hutool.json.JSONObject staffs = provider.getStaffs(s, orgCode, "", 1, 10);
                    log.info("send-Sms-staffs:{}", JSONObject.toJSONString(staffs));

                    if (staffs != null && staffs.getJSONArray("datas") != null) {
                        cn.hutool.json.JSONObject datas = staffs.getJSONArray("datas").getJSONObject(0);
                        if (datas == null) {
                            telephone = "";
                            staffName = "";
                        } else {
                            telephone = datas.getStr("phone");
                            staffName = StringUtils.isEmpty(datas.getStr("staffName")) ? "" : datas.getStr("staffName");
                        }

                    } else {
                        continue;
                    }

                    jobInfo = staffName + "(" + s + ")";
                    if (pushSMS(param, sendSms, phoneAtomic, telephone, "sms"
                            , spId, iMEI,
                            value, report, con, strategyId, 0, sendType, snowflakeId, content, supIMEI, date, 1, jobInfo))
                        continue;
                }
            }
            Integer pushLevel = ext.getPushLevel();
            if (pushLevel != null || pushLevel != 0) {
                //走客户联系人
                if (!CollectionUtil.isEmpty(list)) {
                    List<Integer> objs = new ArrayList<>();
                    list.forEach(stringObjectMap -> {
                        objs.add(Integer.parseInt(stringObjectMap.get("level") + ""));
                    });
                    if (!objs.contains(pushLevel)) {
                        List<Map<String, Object>> listCopy = new ArrayList<>();
                        for (Map<String, Object> map : list) {
                            if (pushLevel > Integer.parseInt(map.get("level") + "")) {
                                listCopy.add(map);
                            }
                        }

                        if (CollectionUtil.isEmpty(listCopy)) {
                            log.info("sendSms-pushLevel，此级别没有合适的下级发送人：{}，客户id:{}"
                                    , pushLevel, con);
                        } else {
                            listCopy.sort((o1, o2) -> {
                                return -Integer.parseInt(o1.get("level") + "")
                                        + Integer.parseInt(o2.get("level") + "");
                            });
                            pushLevel = Integer.parseInt(listCopy.get(0).get("level") + "");
                        }
                    }
                    for (Map<String, Object> stringObjectMap : list) {
                        log.info("sendSms-level:{}", Integer.parseInt(stringObjectMap.get("level") + ""));
                        log.info("sendSms-pushLevel:{}", pushLevel);
                        if (Integer.parseInt(stringObjectMap.get("level") + "")
                                == pushLevel || pushLevel.equals(stringObjectMap.get("level"))) {
                            String telephone = stringObjectMap.get("telephone") + "";
                            if (!StringUtils.isEmpty(telephone)) {
                                String objInfo = info;
                                if (pushSMS(param, sendSms, phoneAtomic, telephone, "sms", spId, iMEI,
                                        value, report, con, strategyId, pushLevel, sendType, snowflakeId, content, supIMEI, date,
                                        0, objInfo)) continue;
                            } else {
                                pushLevel = pushLevel + 1;
                            }
                        }
                    }
                }
            }
            //额外手机号：
            String sendPhones = ext.getSendPhones();

            log.info("send-sendPhones:{}", JSONObject.toJSONString(ext));
            if (!StringUtils.isEmpty(sendPhones)) {
                String[] split = sendPhones.split(this.split);
                String jobInfo = info;
                for (String s : split) {
                    log.info("send-s:{}", JSONObject.toJSONString(s));
                    pushSMS(param, sendSms, phoneAtomic, s, "sms"
                            , spId, iMEI,
                            value, report, con, strategyId, 0, sendType, snowflakeId, content, supIMEI, date, 3, jobInfo);
                }
            }

        } catch (Exception e) {
            log.error("sendSms-error:{}", e);
            return sendSms;
        }

        if (phoneAtomic.get() == null) {
            return sendSms;
        } else {
            sendSms.put("phone", phoneAtomic.get());
            return sendSms;
        }
    }

    private boolean pushSMS(Map<String, Object> param, Map<String, String> sendSms,
                            AtomicReference<String> phoneAtomic,
                            String telephone, String msgType, String spId, String iMEI,
                            Integer value, int report, String con, Object strategyId,
                            Integer level, int sendType, long snowflakeId,
                            String content, String supIMEI, Date date, int type, String notifyObjInfo) {
        //给他发
        try {
            ValueOperations valueOperations = redisTemplate.opsForValue();
            Object o = valueOperations.get(Constants.WARNING_PHONE + "-" + telephone);
            log.info("detailOpt-获取手机号发送次数:{}:{}", telephone, o);
            if (o != null && Integer.parseInt(o + "") >= 10) {
                sendSms.put("phone", phoneAtomic.get());
                sendSms.put("errorMsg", "此手机超过24小时发送次数");
                saveWarningRecord(spId, iMEI, value, report, con, strategyId,
                        level, date, sendType, snowflakeId, 1, content,
                        supIMEI, "此手机超过24小时发送次数", sendSms.get("receiptCode"), telephone, type, notifyObjInfo);
                return true;
            }

            log.info("detailOpt-本次发送短信内容:{}:{}msgType:{}", telephone, param, msgType);
            if (StringUtils.isEmpty(telephone)) {
                saveWarningRecord(spId, iMEI, value, report, con, strategyId,
                        level, date, sendType, snowflakeId, 1, content,
                        supIMEI, "手机号不能为空", "", telephone, type, notifyObjInfo);
                return false;
            }
            //调用外部短信接口
            String msgCode = Constants.WARN_STRATEGY;
            if (!StringUtils.isEmpty(param.get("smsMsgCode"))) {
                msgCode = param.get("smsMsgCode").toString();
            }
            param.remove("smsMsgCode");
            String orgCode = companyService.getOrgCode(spId, con);
            Map<String, Object> sms = sendMessageService
                    .sendSms(sendMessageService
                                    .getRequestParam(telephone
                                            , msgCode, orgCode
                                            , param, msgType, null, null, null, 0)
                            , "");
            Object errorMsg = "";
            int sendResult = 0;
            try {
                if (sms.get("result") != null && sms.get("result").equals(true)) {
                    Integer count = 1;
                    if (o != null) {
                        count = Integer.parseInt(o + "") + 1;
                    }
                    valueOperations.set(Constants.WARNING_PHONE + "-" + telephone
                            , count, 1L, TimeUnit.DAYS);
                }else{
                    errorMsg = null==sms.get("errMsg")?errorMsg:sms.get("errMsg");
                    sendResult = 1;
                }
                if (sms.get("data") != null && !ObjectUtils.isEmpty(sms.get("data"))) {
                    log.info("detailOpt—短信发送人；{}", telephone);
                    HashMap<String, Object> req = new HashMap<>();
                    req.put("ids", sms.get("data"));
                    req.put("orgCode", orgCode);
                    try {
                        Map<String, Object> map = sendMessageService.subTaskDetail(req, "");
                        if (map != null) errorMsg = map.get("errorMsg");
                    } catch (Exception e) {
                        log.info("subTaskDetail-error:{}", e);
                    }
                    if (!StringUtils.isEmpty(errorMsg)) {
                        sendSms.put("errorMsg", errorMsg.toString());
                        sendResult = 1;
                    }
                    log.info("sendSms-发送remark:{}", errorMsg);
                    sendSms.put("receiptCode", JSONObject.toJSONString(sms.get("data")));
                }
            } catch (Exception e) {
                log.error("sms-error:{}", e);
            }
            saveWarningRecord(spId, iMEI, value, report, con, strategyId,
                    level, date, sendType, snowflakeId, sendResult, content,
                    supIMEI, errorMsg, StringUtils.isEmpty(sms.get("data")) ? "" : sms.get("data") + "", telephone, type, notifyObjInfo);

            log.info("sendSms-发送日志:{}回执消息:{},处理结果：{}", telephone, JSONObject.toJSONString(sms),
                    JSONObject.toJSONString(sendSms));
            phoneAtomic.set(telephone + "");
        } catch (Exception e) {
            log.error("pushSMS-error:{}", e);
        }
        return false;
    }
}
